﻿using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using XYS.Core.Models;
using XYS.Core.Util;
using XYS.Service.Core.Util.Helper;

namespace XYS.Core.Service.APILoggerService
{
    /// <summary>
    /// API 接口请求 日志服务
    /// </summary>
    public class APILoggerService : IAPILoggerService
    {
        /// <summary>
        /// 队列
        /// </summary>
        private readonly static ConcurrentQueue<APILoggerInfo> _que = new();

        /// <summary>
        /// API日志通道接口
        /// </summary>
        private readonly IAPILogChannel apiILogChannel;

        private readonly ILogger<APILoggerService> logger;
        /// <summary>
        /// 注入器
        /// </summary>
        /// <param name="loggerFactory"></param>
        /// <param name="apiILogChannel"></param>
        public APILoggerService(ILoggerFactory loggerFactory, IAPILogChannel apiILogChannel = null)
        {
            this.logger = loggerFactory.CreateLogger<APILoggerService>();
            this.apiILogChannel = apiILogChannel;
        }

        /// <summary>
        /// 初始
        /// </summary>
        public Task InitAsync()
        {
            if (this.apiILogChannel == null)
                return Task.CompletedTask;

            return Task.Run(() =>
            {
                while (true)
                {
                    //是否打印日志（每30分钟 打印一次日志的处理过程）
                    bool isShowLog = GlobalCoreSetting.APIRequestLogSetting.Debug;
                    bool enableMQ = GlobalCoreSetting.APIRequestLogSetting.UseMQ && !GlobalCoreSetting.APIRequestLogSetting.APIRequestLogQuqueName.IsNullOrWhiteSpace() && MQLocalHelper.rabbitMQSetting != null;
                    try
                    {
                        if (_que.IsEmpty) continue;
                        int _queCount = _que.Count;

                        if (_que.Count > 1000)
                            logger.LogWarning($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] API 日志积压[{_que.Count}]");

                        List<APILoggerInfo> logList = new();
                        //出栈，最多出 5000 条
                        for (int i = 0; i < 5000 && !_que.IsEmpty; i++)
                        {
                            if (_que.TryDequeue(out var item))
                                logList.Add(item);
                        }
                        if (logList.IsNullOrEmpty()) continue;

                        ConcurrentQueue<APILoggerInfo> _queES = new();
                        if (isShowLog)
                        {
                            logger.LogWarning($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] API 日志处理，日志是否进入MQ[{enableMQ}]，处理日志线程数量[{GlobalCoreSetting.APIRequestLogSetting.LogParallelForCount}]，当前日志总量[{_queCount}]，本次处理日志量[{logList.Count}]");
                        }

                        //如果配置了MQ。则进入MQ队列，否则直接进入ES
                        if (enableMQ)
                        {
                            try
                            {
                                //进入MQ
                                MQLocalHelper.PublishBatch(GlobalCoreSetting.APIRequestLogSetting.APIRequestLogQuqueName, logList);
                                continue;
                            }
                            catch (Exception ex)
                            {
                                if (isShowLog)
                                    logger.LogError($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] API 日志处理，进入MQ 出现异常{ex.ToJson()}");
                            }
                        }

                        //直接进入ES
                        foreach (var item in logList)
                            _queES.Enqueue(item);

                        //如果没有进入MQ，则直接进入ES
                        if (_queES.Count > 0)
                        {
                            if (GlobalCoreSetting.APIRequestLogSetting.UseMQ && !GlobalCoreSetting.APIRequestLogSetting.APIRequestLogQuqueName.IsNullOrWhiteSpace() && MQLocalHelper.rabbitMQSetting != null)
                                logger.LogWarning($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] API 日志进入ES[{_queES.Count}]");

                            try
                            {
                                apiILogChannel?.EnterCannel(_queES);
                            }
                            catch { }
                        }
                        if (isShowLog)
                        {
                            logger.LogWarning($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] API 日志处理完毕，处理总量[{logList.Count}]，进入ES的日志数量[{_queES.Count}]");
                            logger.LogWarning($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] API 日志处理前数量[{_queCount}] 处理后当前总量[{_que.Count}]，日志总量变化[{_queCount - _que.Count}]");
                        }
                    }
                    finally
                    {
                        Thread.Sleep(50);
                    }
                }
            });
        }

        /// <summary>
        /// 新的日志进入队列
        /// </summary>
        /// <returns></returns>
        public void AddLog(APILoggerInfo arg)
        {
            if (!GlobalCoreSetting.ApiLoggerSetting.Enable || this.apiILogChannel == null) return;

            _que.Enqueue(arg);
        }

        /// <summary>
        /// 新的日志进入队列
        /// </summary>
        /// <returns></returns>
        public void AddLog(IEnumerable<APILoggerInfo> request)
        {
            if (!GlobalCoreSetting.ApiLoggerSetting.Enable || this.apiILogChannel == null) return;

            //批量压栈
            foreach (var item in request)
                _que.Enqueue(item);
        }

    }
}
